﻿using System;
using System.Data.Linq;
using System.Data.SqlClient;
using System.Linq;

namespace StreetPacMan.Server
{
    public interface IEntitiesStorage
    {
        Entity[] GetAllPlayersInGame(int gameId);
        Entity[] GetAllApplesInGame(Game game);
        Entity AddEntityInGame(Game game, string entityName, EntityRole role);
        Entity GetEntityById(int entityId);
        void UpdateEntity(int entityId, bool isEnabled, double geoLat, double geoLng);
        void RemoveApplesByIds(int[] appleIds);
    }

    public class EntitiesStorage : IEntitiesStorage
    {
        private readonly string _ConnectionString;

        public EntitiesStorage(IConnectionStringProvider connectionStringProvider)
        {
            _ConnectionString = connectionStringProvider.GetConnectionString();
        }

        public Entity[] GetAllPlayersInGame(int gameId)
        {
            using (var sqlConnection = new SqlConnection(_ConnectionString))
            using (var pacManDataContext = new PacManDataContext(sqlConnection))
            {
                var dataLoadOptions = new DataLoadOptions();
                dataLoadOptions.LoadWith<Entity>(x => x.Game);
                pacManDataContext.LoadOptions = dataLoadOptions;

                return pacManDataContext
                    .Entities
                    .Where(x => x.GameId == gameId)
                    .Where(x => (EntityRole)x.Role == EntityRole.Pacman || (EntityRole)x.Role == EntityRole.Ghost)
                    .ToArray();
            }
        }

        public Entity[] GetAllApplesInGame(Game game)
        {
            using (var sqlConnection = new SqlConnection(_ConnectionString))
            using (var pacManDataContext = new PacManDataContext(sqlConnection))
            {
                var dataLoadOptions = new DataLoadOptions();
                dataLoadOptions.LoadWith<Entity>(x => x.Game);
                pacManDataContext.LoadOptions = dataLoadOptions; 
                
                return pacManDataContext
                    .Entities
                    .Where(x => x.GameId == game.Id)
                    .Where(x => (EntityRole)x.Role == EntityRole.Apple)
                    .ToArray();
            }
        }

        public Entity AddEntityInGame(Game game, string entityName, EntityRole role)
        {
            using (var sqlConnection = new SqlConnection(_ConnectionString))
            using (var pacManDataContext = new PacManDataContext(sqlConnection))
            {
                var dataLoadOptions = new DataLoadOptions();
                dataLoadOptions.LoadWith<Entity>(x => x.Game);
                pacManDataContext.LoadOptions = dataLoadOptions;

                var entity = new Entity
                                 {
                                     GameId = game.Id,
                                     Role = (int) role,
                                     Name = entityName,
                                     VisibleToOtherPlayers = true
                                 };
                pacManDataContext.Entities.InsertOnSubmit(entity);
                pacManDataContext.SubmitChanges();
                var a =entity.Game.LastGameMessage;
                return entity;
            }
        }

        public Entity GetEntityById(int entityId)
        {
            using (var sqlConnection = new SqlConnection(_ConnectionString))
            using (var pacManDataContext = new PacManDataContext(sqlConnection))
            {
                var dataLoadOptions = new DataLoadOptions();
                dataLoadOptions.LoadWith<Entity>(x => x.Game);
                pacManDataContext.LoadOptions = dataLoadOptions; 
                
                return pacManDataContext
                    .Entities
                    .Where(x => x.Id == entityId)
                    .FirstOrDefault();
            }
        }

        public void UpdateEntity(int entityId, bool isEnabled, double geoLat, double geoLng)
        {
            using (var sqlConnection = new SqlConnection(_ConnectionString))
            using (var pacManDataContext = new PacManDataContext(sqlConnection))
            {
                var updateEntity = pacManDataContext
                    .Entities
                    .Where(x => x.Id == entityId)
                    .First();
                updateEntity.VisibleToOtherPlayers = isEnabled;
                updateEntity.LastGeoLat = geoLat;
                updateEntity.LastGeoLon = geoLng;
                pacManDataContext.SubmitChanges();
            }
        }

        public void RemoveApplesByIds(int[] appleIds)
        {
            using (var sqlConnection = new SqlConnection(_ConnectionString))
            using (var pacManDataContext = new PacManDataContext(sqlConnection))
            {
                pacManDataContext
                    .Entities.DeleteAllOnSubmit(pacManDataContext
                                                    .Entities
                                                    .Where(x => appleIds.Contains(x.Id)));
                pacManDataContext.Orders.InsertAllOnSubmit(
                    appleIds.Select(x => new Order {RemovalTime = DateTime.Now, RemovedAppleId = x}));

                pacManDataContext.SubmitChanges();
            }
        }

        //public void RemoveAppleById(int appleId)
        //{
        //    using (var sqlConnection = new SqlConnection(_ConnectionString))
        //    using (var pacManDataContext = new PacManDataContext(sqlConnection))
        //    {
        //        var dataLoadOptions = new DataLoadOptions();
        //        dataLoadOptions.LoadWith<Entity>(x => x.Game);
        //        pacManDataContext.LoadOptions = dataLoadOptions; 
                
        //        pacManDataContext
        //            .Entities
        //            .DeleteOnSubmit(pacManDataContext
        //                                .Entities
        //                                .Where(x => x.Id == appleId)
        //                                .FirstOrDefault());
        //        pacManDataContext.SubmitChanges();
        //    }
        //}
    }
}